using System;
using System.Collections.Generic;

namespace SS.Common.Threading.JobExecutor
{
    #region Used namespaces

    

    #endregion

    /// <summary>
    /// Direct job executor using caller thread without queue
    /// </summary>
    /// <typeparam name="T">Type of the job
    /// </typeparam>
    public class DirectJobExecutor<T> : IJobExecutor<T>
        where T : class, IJob
    {
        /// <summary>
        /// Exception handler, can be null
        /// </summary>
        private volatile ExecutorExceptionHandler<T> exceptionHandler;

        /// <summary>
        /// Gets or sets the exception handler
        /// </summary>
        public ExecutorExceptionHandler<T> ExceptionHandler
        {
            get
            {
                return this.exceptionHandler;
            }

            set
            {
                this.exceptionHandler = value;
            }
        }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
        }

        /// <summary>
        /// initialize
        /// </summary>
        public void Initialize()
        {
        }

        /// <summary>
        /// No queue just execute the job directly
        /// </summary>
        /// <param name="job">
        /// The job to execute
        /// </param>
        public void Queue(T job)
        {
            if (job == null)
            {
                throw new NullReferenceException("Job should not null");
            }

            try
            {
                job.Execute();
            }
            catch (Exception e)
            {
                this.NotifyException(job, e);
            }
        }

        /// <summary>
        /// Reject a job with reason by call to reject handler
        /// </summary>
        /// <param name="job">
        /// The job cause exception
        /// </param>
        /// <param name="exception">
        /// The occured exception
        /// </param>
        private void NotifyException(T job, Exception exception)
        {
            var handler = this.exceptionHandler;
            if (handler != null)
            {
                handler.Invoke(this, job, exception);
            }
        }

        /// <summary>
        /// there is nothing to stop
        /// </summary>
        /// <param name="force">
        /// force stop or not
        /// </param>
        /// <returns>
        /// Always return empty list
        /// </returns>
        public List<T> Stop(bool force)
        {
            return new List<T>();
        }

        /// <summary>
        /// No need to wait anything
        /// </summary>
        /// <param name="millisecondsTimeout">
        /// Number of milliseconds to wait
        /// </param>
        /// <returns>
        /// Always return true
        /// </returns>
        public bool WaitForTermination(int millisecondsTimeout)
        {
            return true;
        }
    }
}
